/**** MODULO per l'IO delle mappe -------------------------------------*/

:- use_module('types/syntax').
:- dynamic num/2.
:- no_check(write_atom(_,_)).
:- consult('m.pl').
check_me :- ensure_loaded('types/chk'),
	load([geometry,io_map]).

/*----------------------------------------------------------------------*/

% 0 ------------------------------------predicati aperti

pred save_dims(number, number, file_name).
%   save_dims(+DX, +DY, +File)  is DET.
%    save(DX,DY,File)  salva in File un predicato
%    contenente le dimensioni DX, DY della mappa

pred save(sym_char, number, number, file_name).
%   save(+C,+X, +Y, +File) is DET.
%    save(C, X, Y, File)  salva in file un predicato
%    che indica la tipologia di terreno dell'area
%    di coordinate (X,Y), codificata dal codice C

%    NOTA IMPORTANTE:  codice -1 = assenza informazioni
%    esplicite, si usera' un tipo di terreno di default

% 1 ----------------------------------- CARICAMENTO MAPPA


%	read_map(+In, +Out) is det
%       carica in Out la rappresentazione della mappa in In,
%       usando il predicato aperto save

read_map(FileIn, MapFile) :-
	open(FileIn, read, In),
	open(MapFile, write, Out),
	
	write_atom(Out,:- dynamic(cella/2)),
	retractall(cella(_,_)),

	read_dims(In, DX, DY),
	save_dims(DX,DY,Out),

	get_map(1,DX,DY,In, Out),
	
	close(In),
	close(Out),

	consult('m.pl'),
	aggregate_all(count,cella(pozzo,_),Pozzi),
	aggregate_all(count,cella(tesoro,_),Tesori),
	aggregate_all(count,cella(wumpus,_),Wumpus),
	retractall(num(_,_)),
	assert(num(pozzi,Pozzi)),
	assert(num(tesori,Tesori)),
	assert(num(wumpus,Wumpus)).

get_map(Y, _DX, DY, Fin, MapF) :-
	Y =< DY,
	at_end_of_stream(Fin),
	close(Fin),
	close(MapF),
	throw('UNESPECTED END OF FILE').

get_map(Y, DX, DY, Fin, MapF) :-
	Y =< DY,
	read_line_to_chars(Fin,Row),
	row_to_map(1, DX, Y, Row, MapF),
	Y1 is Y+1,
	get_map(Y1, DX, DY, Fin, MapF).
get_map(Y, _DX, DY, _FileIn, _MapFile) :-
	Y > DY.

% 3 ---------------------------------------caricamento righe

row_to_map(X,DX,Y,[Code|Row], MapF) :-
	X =< DX,
	save(Code,X,Y,MapF),
	X1 is X+1,
	row_to_map(X1,DX,Y,Row,MapF).
row_to_map(X,DX,Y,[], MapF) :-
	X =< DX,
	save(' ',X,Y,MapF),
	X1 is X+1,
	row_to_map(X1,DX,Y,[],MapF).
row_to_map(X,DX,_,_, _MapF) :-
	X > DX,!.

% 4 ------------------------------------ caricamento dimensioni

read_dims(File, DX, DY) :-
	read_line_to_codes(File,Row),
	to_cifra(Row, RowX),
	get_int(RowX,Next, 0, DX),
	to_cifra(Next,RowY),
	get_int(RowY, _, 0, DY),
	DX > 0,
	DY > 0, !
	;
	throw('manca o e'' errata la riga delle dimensioni').


%	AUSILIARI ------------------------------------------------------

read_line_to_chars(File, Row) :-
	read_line_to_codes(File, CRow),
	maplist(map_to_char, CRow, Row).

map_to_char(Code, Char) :-
	atom_chars(Char,[Code]).

get_int([Code|RowIn], RowOut, IntIn, IntOut) :-
	is_cifra(Code,C) ->
	      NewInt is 10*IntIn+C,
              get_int(RowIn, RowOut, NewInt, IntOut)
	      ;
	      RowOut=[Code|RowIn],
	      IntOut=IntIn.
get_int([],[],I,I).

to_cifra([Code|RowIn], RowOut) :-
	not(is_cifra(Code,_)) ->
              to_cifra(RowIn, RowOut)
	      ;
	      RowOut = [Code|RowIn].
	      
is_cifra(Code,Num) :-
	Num is Code-48,
	Num >= 0,
	Num < 10.